﻿using Microsoft.Extensions.Options;
using RestSharp;
using Shop.Core.Redis;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

namespace Shop.Core.ERP
{
    public class ERPProvider : IERPProvider
    {
        private readonly IRedisProvider _redisProvider;
        private readonly ERPOptions _erpOptions;

        public ERPProvider(IOptions<ERPOptions> options
            , IRedisProvider redisProvider)
        {
            _redisProvider = redisProvider;
            _erpOptions = options.Value;
        }

        public async Task<string> GetAccessToken()
        {
            var data = await _redisProvider.StringGetAsync("ERPAccessToken");
            if (!string.IsNullOrEmpty(data))
                return data;
            else
            {
                var timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString();
                var code = RandomString();
                Hashtable ht = new();
                ht.Add("charset", "utf-8");
                ht.Add("app_key", _erpOptions.AppKey);
                ht.Add("timestamp", timestamp);
                ht.Add("grant_type", "authorization_code");
                ht.Add("code", code);
                var sign = Sign(_erpOptions.AppSecret, ht);
                var client = new RestClient("https://openapi.jushuitan.com");
                var request = new RestRequest("openWeb/auth/getInitToken", Method.Post);
                request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
                request.AddParameter("app_key", _erpOptions.AppKey);
                request.AddParameter("charset", "utf-8");
                request.AddParameter("timestamp", timestamp);
                request.AddParameter("grant_type", "authorization_code");
                request.AddParameter("code", code);
                request.AddParameter("sign", sign);
                RestResponse response = client.Execute(request);
                var retrundata = JsonSerializer.Deserialize<ReturnData<InitTokenReturnData>>(response.Content);
                if (retrundata.code == 0)
                {
                    await _redisProvider.StringSetAsync("ERPAccessToken", retrundata.data.access_token, new TimeSpan(20, 0, 0, 0));
                    return retrundata.data.access_token;
                }
            }
            return String.Empty;
        }

        /// <summary>
        /// 数据签名
        /// </summary>
        /// <param name="signKey"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        private static string Sign(string signKey, Hashtable param)
        {

            ArrayList keys = new ArrayList(param.Keys);
            keys.Sort(); //按字母顺序进行排序
            string resultStr = "";
            foreach (string key in keys)
            {
                if (key != null && key != "" && key != "sign")
                {
                    resultStr = resultStr + key + param[key];
                }
            }
            resultStr = signKey + resultStr;
            MD5 md5 = MD5.Create();
            byte[] rstRes = md5.ComputeHash(Encoding.UTF8.GetBytes(resultStr));
            string hex = BitConverter.ToString(rstRes, 0).Replace("-", string.Empty).ToLower();
            return hex;
        }

        /// <summary>
        /// 上传订单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> UploadOrder(object input)
        {
            var data = JsonSerializer.Serialize(input);
            var timestamp = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString();
            var token = await GetAccessToken();
            Hashtable ht = new();
            ht.Add("biz", data);
            ht.Add("charset", "utf-8");
            ht.Add("app_key", _erpOptions.AppKey);
            ht.Add("access_token", token);
            ht.Add("timestamp", timestamp);
            ht.Add("version", "2");
            var sign = Sign(_erpOptions.AppSecret, ht);

            var client = new RestClient("https://openapi.jushuitan.com");
            var request = new RestRequest("open/jushuitan/orders/upload", Method.Post);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            request.AddParameter("access_token", token);
            request.AddParameter("app_key", _erpOptions.AppKey);
            request.AddParameter("biz", data);
            request.AddParameter("charset", "utf-8");
            request.AddParameter("timestamp", timestamp);
            request.AddParameter("version", "2");
            request.AddParameter("sign", sign);
            RestResponse response = client.Execute(request);
            var returndata = JsonSerializer.Deserialize<ReturnData<OrderUploadReturnData>>(response.Content);
            if (returndata.code == 0)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 随机字符串
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private static string RandomString(int length = 6)
        {
            char[] arrChar = new char[]{
               'a','b','d','c','e','f','g','h','i','j','k','l','m','n','p','r','q','s','t','u','v','w','z','y','x',
               '0','1','2','3','4','5','6','7','8','9',
               'A','B','C','D','E','F','G','H','I','J','K','L','M','N','Q','P','R','T','S','V','U','W','X','Y','Z'};
            StringBuilder sb = new();
            Random rnd = new();
            for (var i = 0; i < length; i++)
            {
                sb.Append(arrChar[rnd.Next(arrChar.Length)]);
            }
            return sb.ToString();
        }
    }
}
